package com.minimalist.lindi.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.minimalist.common.config.exception.BusinessException;
import com.minimalist.common.config.mybatis.bo.PageResp;
import com.minimalist.common.entity.basic.enums.FileEnum;
import com.minimalist.common.entity.basic.vo.file.FileUploadRespVO;
import com.minimalist.common.entity.lindi.enums.LindiTradeApplicationEnum;
import com.minimalist.common.entity.lindi.enums.LindiTradeApplicationFileEnum;
import com.minimalist.common.entity.lindi.enums.LindiTradeApplicationOperatorEnum;
import com.minimalist.common.entity.lindi.enums.TradeStatusEnum;
import com.minimalist.common.entity.lindi.po.*;
import com.minimalist.common.entity.lindi.vo.tradeapplication.LindiTradeApplicationAgreeVO;
import com.minimalist.common.entity.lindi.vo.tradeapplication.LindiTradeApplicationQueryVO;
import com.minimalist.common.entity.lindi.vo.tradeapplication.LindiTradeApplicationVO;
import com.minimalist.common.entity.lindi.vo.tradeapplicationfile.LindiTradeApplicationFileVO;
import com.minimalist.common.entity.lindi.vo.tradeapplicationoperator.LindiTradeApplicationOperatorVO;
import com.minimalist.common.entity.lindi.vo.tradeapplicationtemplateconfirmletter.LindiTradeApplicationTemplateConfirmLetterVO;
import com.minimalist.common.entity.lindi.vo.tradeapplicationtemplatecontract.LindiTradeApplicationTemplateContractVO;
import com.minimalist.common.feign.client.basic.FileFeignClient;
import com.minimalist.common.feign.encoder.ByteArrayMultipartFile;
import com.minimalist.common.response.R;
import com.minimalist.common.utils.JwtUtil;
import com.minimalist.common.utils.UnqIdUtil;
import com.minimalist.lindi.mapper.*;
import com.mybatisflex.core.paginate.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author 11987
 */
@Component
public class LindiTradeApplicationManager{
    private static final Logger log = LoggerFactory.getLogger(LindiTradeApplicationManager.class);
    @Autowired
    private LindiTradeApplicationMapper lindiTradeApplicationMapper;

    @Autowired
    private LindiTradeApplicationOperatorMapper lindiTradeApplicationOperatorMapper;

    @Autowired
    private LindiTradeApplicationFileMapper lindiTradeApplicationFileMapper;

    @Autowired
    private LindiContractTemplateMapper lindiContractTemplateMapper;

    @Autowired
    private LindiTradeApplicationTemplateConfirmLetterMapper lindiTradeApplicationTemplateConfirmLetterMapper;

    @Autowired
    private LindiTradeApplicationTemplateContractMapper lindiTradeApplicationTemplateContractMapper;

    @Autowired
    private ContractTemplateManager contractTemplateManager;

    @Autowired
    private FileFeignClient fileFeignClient;

    @Transactional(rollbackFor = Exception.class)
    public void insertTradeApplicationFiles(Long tradeApplicationId, List<Long> fileIds){
        if (CollectionUtil.isNotEmpty(fileIds)){
            List<LindiTradeApplicationFile> list = fileIds.stream().map(f -> {
                LindiTradeApplicationFile file = new LindiTradeApplicationFile();
                file.setTradeApplicationFileId(f);
                file.setTradeApplicationId(tradeApplicationId);
                file.setFileType(FileEnum.FileSource.LINDI_TRADE_ATTACHMENT.getCode());
                return file;
            }).toList();
            lindiTradeApplicationFileMapper.insertBatch(list);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void addAgreeTradeApplicationOperator(LindiTradeApplicationAgreeVO agreeVO){
        LindiTradeApplicationOperator operator = new LindiTradeApplicationOperator();
        operator.setTradeApplicationOperatorId(UnqIdUtil.uniqueId());
        operator.setTradeApplicationId(agreeVO.getTradeApplicationId());
        operator.setCreateId(agreeVO.getUpdateId());
        operator.setUpdateId(agreeVO.getUpdateId());
        operator.setCreateTime(agreeVO.getUpdateTime());
        operator.setUpdateTime(agreeVO.getUpdateTime());
        if (Objects.equals(agreeVO.getAgree()
                , LindiTradeApplicationEnum.AgreeEnum.AGREE.getCode())){
            operator.setContent(LindiTradeApplicationEnum.AgreeEnum.AGREE.getDesc());
        } else if (Objects.equals(agreeVO.getAgree()
                , LindiTradeApplicationEnum.AgreeEnum.DISAGREE.getCode())){
            operator.setContent(LindiTradeApplicationEnum.AgreeEnum.DISAGREE.getDesc());
        }
        lindiTradeApplicationOperatorMapper.insert(operator);
    }

    @Transactional(rollbackFor = Exception.class)
    public LindiTradeApplicationFileVO createTradeApplicationFile(
            LindiTradeApplicationFileVO fileVO
            , LindiTradeApplicationVO tradeApplicationVO){
        // 从resource目录读取文件
        log.info("创建交易申请文件，tradeApplicationVO: {}, fileVO: {}", tradeApplicationVO, fileVO);

        // 使用Spring的ResourceLoader加载资源文件
        try{
            org.springframework.core.io.Resource resource =
                    new org.springframework.core.io.ClassPathResource(fileVO.getFileTypeDesc());
            File file = resource.getFile();

            Assert.isTrue(file.exists() && file.canRead()
                    , () -> new BusinessException("资源文件不存在或不可读"));

            // 创建ByteArrayMultipartFile对象
            ByteArrayMultipartFile multipartFile = new ByteArrayMultipartFile(file);

            // 调用Feign客户端上传文件
            log.info("开始上传文件: {}", file.getName());
            // 创建FileVO对象传递给Feign接口
            R<FileUploadRespVO> fileUploadRespVOR = fileFeignClient.uploadFile(
                    multipartFile, FileEnum.FileSource
                            .LINDI_TRADE_CONFIRMATION_LETTER.getCode()
                    , fileVO.getCreateId(), fileVO.getUpdateId(), fileVO.getTenantId());
            log.info("上传文件结果 fileUploadRespVOR:{}", fileUploadRespVOR);

            if (fileUploadRespVOR.getData() == null){
                log.error("文件上传失败: {}", file.getName());
                throw new BusinessException("文件上传失败");
            }

            // 保存文件信息到数据库
            FileUploadRespVO fileUploadRespVO = fileUploadRespVOR.getData();
            fileVO.setTradeApplicationFileId(fileUploadRespVO.getFileId());
            fileVO.setFileUrl(fileUploadRespVO.getFileUrl());
            fileVO.setFileName(fileUploadRespVO.getFileName());
            fileVO.setFileSize(fileUploadRespVO.getFileSize());
            fileVO.setCreateTime(tradeApplicationVO.getCreateTime());
            fileVO.setCreateId(tradeApplicationVO.getCreateId());
            fileVO.setUpdateTime(tradeApplicationVO.getUpdateTime());
            fileVO.setUpdateId(tradeApplicationVO.getUpdateId());

            // 保存文件信息到数据库
            fileVO.setTradeApplicationFileId(fileUploadRespVO.getFileId());
            LindiTradeApplicationFile tradeApplicationFile = BeanUtil.copyProperties(
                    fileVO, LindiTradeApplicationFile.class);
            if (tradeApplicationFile != null){
                tradeApplicationFile.setTradeApplicationId(tradeApplicationVO
                        .getTradeApplicationId());
            }
            int insert = lindiTradeApplicationFileMapper.insert(tradeApplicationFile);
            Assert.isTrue(insert == 1, () -> new BusinessException(
                    LindiTradeApplicationFileEnum.ErrorMsgEnum
                            .ADD_TRADE_APPLICATION_FILE_ERROR.getDesc()));

            log.info("文件上传成功: {}, fileId: {}", file.getName(), fileUploadRespVO.getFileId());
            return fileVO;
        } catch (Exception e){
            log.error("文件上传异常: {}", e.getMessage(), e);
            throw new BusinessException("文件上传异常: " + e.getMessage());
        }
    }

    public List<LindiTradeApplicationFileVO> getTradeApplicationFilesByApplicationId(
            Long tradeApplicationId){
        if (tradeApplicationId == null){
            return List.of();
        }
        return lindiTradeApplicationFileMapper
                .selectTradeApplicationFilesByTradeApplicationFileId(tradeApplicationId)
                .stream().map(f -> BeanUtil.copyProperties(
                        f, LindiTradeApplicationFileVO.class))
                .toList();
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteTradeApplicationFilesByTradeApplicationId(Long tradeApplicationId){
        List<LindiTradeApplicationFile> lindiTradeApplicationFiles =
                lindiTradeApplicationFileMapper
                        .selectTradeApplicationFilesByTradeApplicationId(
                                tradeApplicationId);
        if (CollectionUtil.isNotEmpty(lindiTradeApplicationFiles)){
            int delete = lindiTradeApplicationFileMapper
                    .deleteTradeApplicationFilesByTradeApplicationId(tradeApplicationId);
            Assert.isTrue(delete == lindiTradeApplicationFiles.size()
                    , () -> new BusinessException(
                            LindiTradeApplicationFileEnum.ErrorMsgEnum.DELETE_TRADE_APPLICATION_FILE_ERROR
                                    .getDesc()));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteTradeApplicationOperatorsByTradeApplicationId(Long tradeApplicationId){
        List<LindiTradeApplicationOperator> lindiTradeApplicationOperators =
                lindiTradeApplicationOperatorMapper
                        .selectTradeApplicationOperatorsByApplicationId(tradeApplicationId);
        if (CollectionUtil.isNotEmpty(lindiTradeApplicationOperators)){
            int delete = lindiTradeApplicationOperatorMapper
                    .deleteByQuery(com.mybatisflex.core.query.QueryWrapper.create()
                            .eq(LindiTradeApplicationOperator::getTradeApplicationId, tradeApplicationId));
            Assert.isTrue(delete == lindiTradeApplicationOperators.size()
                    , () -> new BusinessException(LindiTradeApplicationOperatorEnum
                            .ErrorMsgEnum.DELETE_TRADE_APPLICATION_OPERATOR_ERROR
                            .getDesc()));
        }
    }

    /**
     * 根据企业用户token查询该企业用户交易申请分页列表
     */
    public PageResp<LindiTradeApplicationVO> getEnterpriseTradeApplicationList(
            String token, LindiTradeApplicationQueryVO queryVO){
        try{
            // 从token中解析企业用户ID
            Long enterpriseAccountId = JwtUtil.getUserId(token);
            if (enterpriseAccountId == null){
                throw new BusinessException("无效的用户token");
            }

            // 设置企业用户ID到查询条件
            queryVO.setEnterpriseAccountId(enterpriseAccountId);

            // 使用mapper直接查询分页数据
            Page<LindiTradeApplication> page = lindiTradeApplicationMapper
                    .selectPageTradeApplicationList(queryVO);

            // 转换为VO对象
            List<LindiTradeApplicationVO> voList = page.getRecords().stream()
                    .map(po -> BeanUtil.copyProperties(po, LindiTradeApplicationVO.class))
                    .toList();

            // 构建分页响应
            PageResp<LindiTradeApplicationVO> pageResp = new PageResp<>();
            pageResp.setRecords(voList);
            pageResp.setTotal(page.getTotalRow());

            return pageResp;
        } catch (Exception e){
            log.error("查询企业交易申请列表异常: {}", e.getMessage(), e);
            throw new BusinessException("查询交易申请列表失败: " + e.getMessage());
        }
    }

    /**
     * 根据企业用户token和交易申请ID查询该交易申请详情信息
     */
    public LindiTradeApplicationVO getEnterpriseTradeApplicationDetail(
            String token, Long tradeApplicationId){
        try{
            // 从token中解析企业用户ID
            Long enterpriseAccountId = JwtUtil.getUserId(token);
            if (enterpriseAccountId == null){
                throw new BusinessException("无效的用户token");
            }

            // 使用mapper直接查询详情
            LindiTradeApplication tradeApplication =
                    lindiTradeApplicationMapper.selectTradeApplicationByTradeApplicationId(tradeApplicationId);

            if (tradeApplication == null){
                return null;
            }

            // 转换为VO对象
            LindiTradeApplicationVO tradeApplicationVO =
                    BeanUtil.copyProperties(tradeApplication, LindiTradeApplicationVO.class);

            // 验证该交易申请是否属于当前企业用户
            if (!enterpriseAccountId.equals(tradeApplicationVO.getEnterpriseAccountId())){
                throw new BusinessException("无权限访问该交易申请");
            }

            // 补充文件信息
            enrichTradeApplicationWithFileInfo(tradeApplicationVO);

            // 补充关联信息
            enrichTradeApplicationWithRelatedInfo(tradeApplicationVO);

            return tradeApplicationVO;
        } catch (Exception e){
            log.error("查询企业交易申请详情异常: {}", e.getMessage(), e);
            throw new BusinessException("查询交易申请详情失败: " + e.getMessage());
        }
    }

    /**
     * 审批交易申请
     *
     * @param agreeVO 审批信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void approveTradeApplication(LindiTradeApplicationAgreeVO agreeVO){
        log.info("开始审批交易申请，参数：{}", agreeVO);

        // 查询交易申请信息
        LindiTradeApplication tradeApplication = lindiTradeApplicationMapper
                .selectTradeApplicationByTradeApplicationId(agreeVO.getTradeApplicationId());
        Assert.notNull(tradeApplication,
                () -> new BusinessException("交易申请不存在"));

        // 根据审批结果更新交易申请状态
        if (Objects.equals(agreeVO.getAgree(),
                LindiTradeApplicationEnum.AgreeEnum.AGREE.getCode())){
            // 审批通过，更新状态为林业局审批通过
            tradeApplication.setTradeStatus(tradeApplication.getTradeStatus() + 1);
            log.info("审批通过，交易申请ID：{}", agreeVO.getTradeApplicationId());

            // 处理交易编号
            if (tradeApplication.getTradeStatus() == 3){
                handleTradeCode(agreeVO, tradeApplication);
                // 根据项目类型查询合同模板并生成确认函
                // 根据项目类型查询合同模板
                LindiContractTemplate contractTemplate =
                        lindiContractTemplateMapper.selectContractTemplateByType("4");
                if (contractTemplate != null){
                    // 设置查询到的模板ID
                    agreeVO.setConfirmLetterTemplateId(contractTemplate.getContractTemplateId());
                    generateConfirmationLetter(agreeVO, tradeApplication);
                }
            }
            if (tradeApplication.getTradeStatus() == 6){
                String type = "";
                if (Objects.equals(tradeApplication.getProjectType(), "2")){
                    type = "3";
                } else if (tradeApplication.getReserveArea() != null && tradeApplication.getPublicForestArea() == null){
                    type = "0";
                } else if (tradeApplication.getReserveArea() == null && tradeApplication.getPublicForestArea() != null){
                    type = "1";
                } else if (tradeApplication.getReserveArea() != null && tradeApplication.getPublicForestArea() != null){
                    type = "2";
                }
                LindiContractTemplate contractTemplate =
                        lindiContractTemplateMapper.selectContractTemplateByType(type);
                if (contractTemplate != null){
                    // 设置查询到的模板ID
                    agreeVO.setConfirmLetterTemplateId(
                            contractTemplate.getContractTemplateId());
                    generateConfirmationLetter(agreeVO, tradeApplication);

                    // 生成合同
                    agreeVO.setContractTemplateId(contractTemplate.getContractTemplateId());
                    agreeVO.setContractType(type);
                    generateContract(agreeVO, tradeApplication);
                }
            }
        } else if (Objects.equals(agreeVO.getAgree(),
                LindiTradeApplicationEnum.AgreeEnum.DISAGREE.getCode())){
            // 审批拒绝，更新状态为已拒绝
            tradeApplication.setTradeStatus(TradeStatusEnum.REJECTED.getCode());
            tradeApplication.setRefuseReason(agreeVO.getRefuseReason());
            log.info("审批拒绝，交易申请ID：{}，拒绝原因：{}",
                    agreeVO.getTradeApplicationId(), agreeVO.getRefuseReason());
        } else{
            throw new BusinessException("无效的审批结果");
        }

        // 更新交易申请信息
        tradeApplication.setUpdateId(agreeVO.getUpdateId());
        tradeApplication.setUpdateTime(agreeVO.getUpdateTime());

        int updateResult = lindiTradeApplicationMapper
                .updateTradeApplicationByTradeApplicationId(tradeApplication);
        Assert.isTrue(updateResult == 1,
                () -> new BusinessException("更新交易申请状态失败"));

        // 添加操作记录
        addApproveTradeApplicationOperator(agreeVO);

        log.info("审批交易申请完成，交易申请ID：{}", agreeVO.getTradeApplicationId());
    }


    /**
     * 添加审批操作记录
     *
     * @param agreeVO 审批信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void addApproveTradeApplicationOperator(LindiTradeApplicationAgreeVO agreeVO){
        LindiTradeApplicationOperator operator = new LindiTradeApplicationOperator();
        operator.setTradeApplicationOperatorId(UnqIdUtil.uniqueId());
        operator.setTradeApplicationId(agreeVO.getTradeApplicationId());
        operator.setCreateId(agreeVO.getUpdateId());
        operator.setUpdateId(agreeVO.getUpdateId());
        operator.setCreateTime(agreeVO.getUpdateTime());
        operator.setUpdateTime(agreeVO.getUpdateTime());

        if (Objects.equals(agreeVO.getAgree(),
                LindiTradeApplicationEnum.AgreeEnum.AGREE.getCode())){
            operator.setContent("林业局审批通过");
        } else if (Objects.equals(agreeVO.getAgree(),
                LindiTradeApplicationEnum.AgreeEnum.DISAGREE.getCode())){
            operator.setContent("林业局审批拒绝：" + agreeVO.getRefuseReason());
        }

        lindiTradeApplicationOperatorMapper.insert(operator);
        log.info("添加审批操作记录成功，交易申请ID：{}", agreeVO.getTradeApplicationId());
    }

    /**
     * 生成确认函
     *
     * @param agreeVO          审批信息
     * @param tradeApplication 交易申请信息
     */
    private void generateConfirmationLetter(LindiTradeApplicationAgreeVO agreeVO
            , LindiTradeApplication tradeApplication){
        try{
            log.info("开始生成确认函，交易申请ID：{}，模板ID：{}，确认函类型：{}",
                    agreeVO.getTradeApplicationId(),
                    agreeVO.getConfirmLetterTemplateId(),
                    agreeVO.getConfirmLetterType());

            // 调用合同模板管理器生成确认函文件
            R<FileUploadRespVO> fileUploadRespVO = contractTemplateManager
                    .generateContract(
                            agreeVO.getTradeApplicationId(),
                            agreeVO.getConfirmLetterTemplateId(),
                            agreeVO.getConfirmLetterType(),
                            agreeVO.getUpdateId(),
                            agreeVO.getTenantId());

            if (fileUploadRespVO != null && fileUploadRespVO.getData() != null){
                // 创建确认函模板记录
                LindiTradeApplicationTemplateConfirmLetterVO confirmLetterVO = new LindiTradeApplicationTemplateConfirmLetterVO();
                confirmLetterVO.setTemplateConfirmLetterId(UnqIdUtil.uniqueId());
                confirmLetterVO.setTradeApplicationId(agreeVO.getTradeApplicationId());
                confirmLetterVO.setConfirmLetterType(agreeVO.getConfirmLetterType());
                confirmLetterVO.setCreateId(agreeVO.getUpdateId());
                confirmLetterVO.setUpdateId(agreeVO.getUpdateId());
                LocalDateTime now = LocalDateTime.now();
                confirmLetterVO.setCreateTime(now);
                confirmLetterVO.setUpdateTime(now);
                confirmLetterVO.setFileId(fileUploadRespVO.getData().getFileId());

                // 保存到数据库
                LindiTradeApplicationTemplateConfirmLetter confirmLetter = BeanUtil.copyProperties(
                        confirmLetterVO, LindiTradeApplicationTemplateConfirmLetter.class);
                int insert = lindiTradeApplicationTemplateConfirmLetterMapper.insert(confirmLetter);
                Assert.isTrue(insert == 1, () -> new BusinessException("插入交易申请确认函模板失败"));

                log.info("确认函生成完成，交易申请ID：{}，文件ID：{}",
                        agreeVO.getTradeApplicationId(), fileUploadRespVO.getData().getFileId());
            } else{
                log.warn("确认函文件生成失败，交易申请ID：{}", agreeVO.getTradeApplicationId());
            }
        } catch (Exception e){
            log.error("生成确认函失败，交易申请ID：{}", agreeVO.getTradeApplicationId(), e);
            // 不抛出异常，避免影响审批流程
        }
    }

    /**
     * 处理交易编号
     *
     * @param agreeVO          审批信息
     * @param tradeApplication 交易申请信息
     */
    private void handleTradeCode(
            LindiTradeApplicationAgreeVO agreeVO, LindiTradeApplication tradeApplication){
        try{
            log.info("开始处理交易编号，交易申请ID：{}，编号类型：{}",
                    agreeVO.getTradeApplicationId(), agreeVO.getTradeCodeType());

            String tradeCode;
            if ("manual".equals(agreeVO.getTradeCodeType())){
                // 手动输入的交易编号
                tradeCode = agreeVO.getTradeCode();
                log.info("使用手动输入的交易编号：{}", tradeCode);
            } else{
                // 自动生成交易编号
                tradeCode = generateTradeCode(tradeApplication);
                log.info("自动生成交易编号：{}", tradeCode);
            }

            // 更新交易申请的交易编号
            tradeApplication.setTradeCode(tradeCode);

            log.info("交易编号处理完成，交易申请ID：{}，交易编号：{}",
                    agreeVO.getTradeApplicationId(), tradeCode);
        } catch (Exception e){
            log.error("处理交易编号失败，交易申请ID：{}", agreeVO.getTradeApplicationId(), e);
            // 不抛出异常，避免影响审批流程
        }
    }

    /**
     * 生成交易编号
     *
     * @param tradeApplication 交易申请信息
     * @return 生成的交易编号
     */
    private String generateTradeCode(LindiTradeApplication tradeApplication){
        try{
            // 生成交易编号规则：LD + 年月日 + 6位随机数字
            // 例如：LD20241201123456
            String dateStr = java.time.LocalDate.now().format(
                    java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"));

            // 生成6位随机数字
            String randomNum = String.format("%06d",
                    (int) (Math.random() * 1000000));

            String tradeCode = "LD" + dateStr + randomNum;

            log.info("自动生成交易编号：{}", tradeCode);
            return tradeCode;
        } catch (Exception e){
            log.error("生成交易编号失败", e);
            // 如果生成失败，使用备用方案：LD + 时间戳
            String fallbackCode = "LD" + System.currentTimeMillis();
            log.warn("使用备用交易编号：{}", fallbackCode);
            return fallbackCode;
        }
    }

    /**
     * 补充交易申请的文件信息
     *
     * @param tradeApplicationVO 交易申请VO
     */
    private void enrichTradeApplicationWithFileInfo(LindiTradeApplicationVO tradeApplicationVO){
        try{
            // 补充红线图文件信息
            if (tradeApplicationVO.getRedlineMapId() != null){
                R<com.minimalist.common.entity.basic.vo.file.FileVO> redlineMapResult =
                        fileFeignClient.getFileByFileId(tradeApplicationVO.getRedlineMapId());
                if (redlineMapResult != null && redlineMapResult.getData() != null){
                    tradeApplicationVO.setRedlineMapFile(redlineMapResult.getData());
                }
            }

            // 补充其他文件信息
            if (CollectionUtil.isNotEmpty(tradeApplicationVO.getOtherFiles())){
                List<com.minimalist.common.entity.basic.vo.file.FileVO> otherFilesVO = new ArrayList<>();
                for (Long fileId : tradeApplicationVO.getOtherFiles()){
                    R<com.minimalist.common.entity.basic.vo.file.FileVO> fileResult =
                            fileFeignClient.getFileByFileId(fileId);
                    if (fileResult != null && fileResult.getData() != null){
                        otherFilesVO.add(fileResult.getData());
                    }
                }
                tradeApplicationVO.setOtherFilesVO(otherFilesVO);
            }
        } catch (Exception e){
            log.warn("补充文件信息失败: {}", e.getMessage());
        }
    }

    /**
     * 生成合同
     *
     * @param agreeVO          审批信息
     * @param tradeApplication 交易申请信息
     */
    private void generateContract(LindiTradeApplicationAgreeVO agreeVO
            , LindiTradeApplication tradeApplication){
        try{
            log.info("开始生成合同，交易申请ID：{}，模板ID：{}，合同类型：{}",
                    agreeVO.getTradeApplicationId(),
                    agreeVO.getContractTemplateId(),
                    agreeVO.getContractType());

            // 调用合同模板管理器生成合同文件
            R<FileUploadRespVO> fileUploadRespVO = contractTemplateManager
                    .generateContract(
                            agreeVO.getTradeApplicationId(),
                            agreeVO.getContractTemplateId(),
                            agreeVO.getContractType(),
                            agreeVO.getUpdateId(),
                            agreeVO.getTenantId());

            if (fileUploadRespVO != null && fileUploadRespVO.getData() != null){
                // 创建合同模板记录
                LindiTradeApplicationTemplateContractVO contractTemplateVO = new LindiTradeApplicationTemplateContractVO();
                contractTemplateVO.setTradeApplicationContractFileId(UnqIdUtil.uniqueId());
                contractTemplateVO.setTradeApplicationId(agreeVO.getTradeApplicationId());
                contractTemplateVO.setFileId(fileUploadRespVO.getData().getFileId());
                contractTemplateVO.setContractType(agreeVO.getContractType());
                contractTemplateVO.setStatus(1);
                contractTemplateVO.setCreateId(agreeVO.getUpdateId());
                contractTemplateVO.setUpdateId(agreeVO.getUpdateId());
                LocalDateTime now = LocalDateTime.now();
                contractTemplateVO.setCreateTime(now);
                contractTemplateVO.setUpdateTime(now);

                // 保存合同模板信息到数据库
                LindiTradeApplicationTemplateContract contractTemplate = BeanUtil.copyProperties(
                        contractTemplateVO, LindiTradeApplicationTemplateContract.class);
                int insert = lindiTradeApplicationTemplateContractMapper.insert(contractTemplate);
                Assert.isTrue(insert == 1, () -> new BusinessException("插入交易申请合同模板失败"));

                log.info("合同生成完成，交易申请ID：{}，文件ID：{}",
                        agreeVO.getTradeApplicationId(), fileUploadRespVO.getData().getFileId());
            } else{
                log.warn("合同文件生成失败，交易申请ID：{}", agreeVO.getTradeApplicationId());
            }
        } catch (Exception e){
            log.error("生成合同失败，交易申请ID：{}", agreeVO.getTradeApplicationId(), e);
            // 不抛出异常，避免影响审批流程
        }
    }

    /**
     * 补充交易申请的关联信息
     *
     * @param tradeApplicationVO 交易申请VO
     */
    private void enrichTradeApplicationWithRelatedInfo(LindiTradeApplicationVO tradeApplicationVO){
        try{
            Long tradeApplicationId = tradeApplicationVO.getTradeApplicationId();

            // 补充交易申请文件列表
            List<LindiTradeApplicationFileVO> fileList = getTradeApplicationFilesByApplicationId(tradeApplicationId);
            tradeApplicationVO.setTradeApplicationFileList(fileList);

            // 补充交易申请操作记录列表
            List<LindiTradeApplicationOperator> operatorList =
                    lindiTradeApplicationOperatorMapper.selectTradeApplicationOperatorsByApplicationId(tradeApplicationId);
            if (CollectionUtil.isNotEmpty(operatorList)){
                List<LindiTradeApplicationOperatorVO> operatorVOList = operatorList.stream()
                        .map(operator -> BeanUtil.copyProperties(operator, LindiTradeApplicationOperatorVO.class))
                        .toList();
                tradeApplicationVO.setTradeApplicationOperatorList(operatorVOList);
            }

            // TODO: 根据业务需要补充其他关联信息
            // 如：审批文件列表、合同列表、发票列表、付款凭证列表、确认函列表等
            // 这些可以根据具体的业务需求和mapper方法来实现

        } catch (Exception e){
            log.warn("补充关联信息失败: {}", e.getMessage());
        }
    }
}